Veremos ahora un ejemplo sencillo usando plantillas.
Seguimos necesitando dos clases, una para nodo y otra para la lista circular. Pero ahora podremos aprovechar las características de las plantillas para crear listas circulares de cualquier tipo de objeto.
Veremos primero las declaraciones de las dos clases que necesitamos:
template<class TIPO> class lista; template<class TIPO> class nodo { public: nodo(TIPO v, nodo<TIPO> *sig = NULL) { valor = v; siguiente = sig; } private: TIPO valor; nodo<TIPO> *siguiente; friend class lista<TIPO>; }; template<class TIPO> class lista { public: lista() { actual = NULL; } ~lista(); void Insertar(TIPO v); void Borrar(TIPO v); bool ListaVacia() { return actual == NULL; } void Mostrar(); void Siguiente(); bool Actual() { return actual != NULL; } TIPO ValorActual() { return actual->valor; } private: nodo<TIPO> *actual; };
Ahora veremos la implementación de estas clases. No difiere demasiado de otros ejemplos.
template<class TIPO> lista<TIPO>::~lista() { nodo<TIPO> *Nodo; // Mientras la lista tenga más de un nodo while(actual->siguiente != actual) { // Borrar el nodo siguiente al apuntado por lista Nodo = actual->siguiente; actual->siguiente = Nodo->siguiente; delete Nodo; } // Y borrar el último nodo delete actual; actual = NULL; } template<class TIPO> void lista<TIPO>::Insertar(TIPO v) { nodo<TIPO> *Nodo; // Creamos un nodo para el nuevo valor a insertar Nodo = new nodo<TIPO>(v); // Si la lista está vacía, la lista será el nuevo nodo // Si no lo está, insertamos el nuevo nodo a continuación del apuntado // por lista if(actual == NULL) actual = Nodo; else Nodo->siguiente = actual->siguiente; // En cualquier caso, cerramos la lista circular actual->siguiente = Nodo; } template<class TIPO> void lista<TIPO>::Borrar(TIPO v) { nodo<TIPO> *Nodo; Nodo = actual; // Hacer que lista apunte al nodo anterior al de valor v do { if(actual->siguiente->valor != v) actual = actual->siguiente; } while(actual->siguiente->valor != v && actual != Nodo); // Si existe un nodo con el valor v: if(actual->siguiente->valor == v) { // Y si la lista sólo tiene un nodo if(actual == actual->siguiente) { // Borrar toda la lista delete actual; actual = NULL; } else { // Si la lista tiene más de un nodo, borrar el nodo de valor v Nodo = actual->siguiente; actual->siguiente = Nodo->siguiente; delete Nodo; } } } template<class TIPO> void lista<TIPO>::Mostrar() { nodo<TIPO> *Nodo = actual; do { cout << Nodo->valor << "-> "; Nodo = Nodo->siguiente; } while(Nodo != actual); cout << endl; } template<class TIPO> void lista<TIPO>::Siguiente() { if(actual) actual = actual->siguiente; }
Eso es todo, ya sólo falta usar nuestras clases para un ejemplo práctico:
#include <iostream> #include "CCadena.h" using namespace std; template<class TIPO> class lista; template<class TIPO> class nodo { public: nodo(TIPO v, nodo<TIPO> *sig = NULL) { valor = v; siguiente = sig; } private: TIPO valor; nodo<TIPO> *siguiente; friend class lista<TIPO>; }; template<class TIPO> class lista { public: lista() { actual = NULL; } ~lista(); void Insertar(TIPO v); void Borrar(TIPO v); bool ListaVacia() { return actual == NULL; } void Mostrar(); void Siguiente(); bool Actual() { return actual != NULL; } TIPO ValorActual() { return actual->valor; } private: nodo<TIPO> *actual; }; template<class TIPO> lista<TIPO>::~lista() { nodo<TIPO> *Nodo; // Mientras la lista tenga más de un nodo while(actual->siguiente != actual) { // Borrar el nodo siguiente al apuntado por lista Nodo = actual->siguiente; actual->siguiente = Nodo->siguiente; delete Nodo; } // Y borrar el último nodo delete actual; actual = NULL; } template<class TIPO> void lista<TIPO>::Insertar(TIPO v) { nodo<TIPO> *Nodo; // Creamos un nodo para el nuevo valor a insertar Nodo = new nodo<TIPO>(v); // Si la lista está vacía, la lista será el nuevo nodo // Si no lo está, insertamos el nuevo nodo a continuación del apuntado // por lista if(actual == NULL) actual = Nodo; else Nodo->siguiente = actual->siguiente; // En cualquier caso, cerramos la lista circular actual->siguiente = Nodo; } template<class TIPO> void lista<TIPO>::Borrar(TIPO v) { nodo<TIPO> *Nodo; Nodo = actual; // Hacer que lista apunte al nodo anterior al de valor v do { if(actual->siguiente->valor != v) actual = actual->siguiente; } while(actual->siguiente->valor != v && actual != Nodo); // Si existe un nodo con el valor v: if(actual->siguiente->valor == v) { // Y si la lista sólo tiene un nodo if(actual == actual->siguiente) { // Borrar toda la lista delete actual; actual = NULL; } else { // Si la lista tiene más de un nodo, borrar el nodo de valor v Nodo = actual->siguiente; actual->siguiente = Nodo->siguiente; delete Nodo; } } } template<class TIPO> void lista<TIPO>::Mostrar() { nodo<TIPO> *Nodo = actual; do { cout << Nodo->valor << "-> "; Nodo = Nodo->siguiente; } while(Nodo != actual); cout << endl; } template<class TIPO> void lista<TIPO>::Siguiente() { if(actual) actual = actual->siguiente; } int main() { lista<int> iLista; lista<float> fLista; lista<double> dLista; lista<char> cLista; lista<Cadena> sLista; // Prueba con <int> iLista.Insertar(20); iLista.Insertar(10); iLista.Insertar(40); iLista.Insertar(30); iLista.Insertar(60); iLista.Mostrar(); cout << "Lista de elementos:" << endl; iLista.Borrar(10); iLista.Borrar(30); iLista.Mostrar(); // Prueba con <float> fLista.Insertar(20.01); fLista.Insertar(10.02); fLista.Insertar(40.03); fLista.Insertar(30.04); fLista.Insertar(60.05); fLista.Mostrar(); cout << "Lista de elementos:" << endl; fLista.Borrar(10.02); fLista.Borrar(30.04); fLista.Mostrar(); // Prueba con <double> dLista.Insertar(0.0020); dLista.Insertar(0.0010); dLista.Insertar(0.0040); dLista.Insertar(0.0030); dLista.Insertar(0.0060); dLista.Mostrar(); cout << "Lista de elementos:" << endl; dLista.Borrar(0.0010); dLista.Borrar(0.0030); dLista.Mostrar(); // Prueba con <char> cLista.Insertar('x'); cLista.Insertar('y'); cLista.Insertar('a'); cLista.Insertar('b'); cLista.Insertar('m'); cLista.Mostrar(); cout << "Lista de elementos:" << endl; cLista.Borrar('y'); cLista.Borrar('b'); cLista.Mostrar(); // Prueba con <Cadena> sLista.Insertar("Hola"); sLista.Insertar("somos"); sLista.Insertar("programadores"); sLista.Insertar("buenos"); sLista.Insertar("!!!!"); sLista.Mostrar(); cout << "Lista de elementos:" << endl; sLista.Borrar("somos"); sLista.Borrar("buenos"); sLista.Mostrar(); cin.get(); return 0; }
© Agosto de 2001 Salvador Pozo, salvador@conclase.net